package com.microframework.boot.datarule.controller;

import java.sql.Date;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.jfinal.kit.StrKit;
import com.microframework.base.core.constants.CacheConstants;
import com.microframework.base.core.dbconfig.DbConfigUtil;
import com.microframework.base.core.util.SecurityUtils;
import com.microframework.base.core.util.UuidUtil;
import com.microframework.base.core.util.sql.DataSourceValidator;
import com.microframework.base.core.util.sql.DbConfigTestUtil;
import com.microframework.base.web.page.PageQuery;
import com.microframework.base.web.resp.R;
import com.microframework.boot.datarule.model.domain.DbConfig;
import com.microframework.boot.datarule.service.IDbConfigService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/data-rule/db")
@Tag(name = "数据源管理", description = "数据源管理相关接口")
public class DbConfigController {

	@Autowired
	private IDbConfigService dbConfigService;

	@PostMapping("/load/all")
	@Operation(summary = "一次性加载数据数据", description = "一次性加载数据数据")
	public R<List<DbConfig>> loadAll(@RequestBody PageQuery<DbConfig> pageQuery) {
		return R.ok(dbConfigService.loadAll(pageQuery));
	}

	@PostMapping("/load/options")
	@Operation(summary = "下拉数据源数据", description = "下拉数据源数据")
	public R<List<DbConfig>> options(@RequestBody PageQuery<DbConfig> pageQuery) {
		return R.ok(dbConfigService.loadAll(pageQuery));
	}

	@Operation(summary = "保存数据源")
	@Parameters({ @Parameter(name = "dbConfig", description = "数据源", required = true) })
	@PostMapping("/save")
	@CachePut(value = CacheConstants.SYS_CACHES, key = "#dbConfig.id")
	public R<DbConfig> save(HttpServletRequest request, @RequestBody DbConfig dbConfig) {
		try {
			if (StrKit.notBlank(dbConfig.getId())) {
				dbConfig.setModifyTime(new Date(System.currentTimeMillis()));
				dbConfig.setModifyUserId(SecurityUtils.getUserId());
				if (dbConfig.update()) {
					return R.ok(dbConfig);
				} else {
					return R.fail("更新失败.");
				}
			} else {
				dbConfig.setId(UuidUtil.getUUID());
				dbConfig.setCreateTime(new Date(System.currentTimeMillis()));
				dbConfig.setCreateUserId(SecurityUtils.getUserId());
				if (dbConfig.save()) {
					return R.ok(dbConfig);
				} else {
					return R.fail("保存失败.");
				}
			}
		} catch (Exception e) {
			return R.fail(e.getMessage());
		}
	}

	@Operation(summary = "删除数据源")
	@Parameters({ @Parameter(name = "id", description = "数据源id", required = true) })
	@DeleteMapping("/detain/{id}")
	@CacheEvict(value = CacheConstants.SYS_CACHES, key = "#id")
	public R<String> deleteById(@PathVariable("id") String id) {
		try {
			DbConfig org = new DbConfig();
			org.setId(id);
			org.setIsDel("1");
			if (org.update()) {
				return R.ok("删除成功.");
			} else {
				return R.fail("删除失败.");
			}
		} catch (Exception e) {
			log.error("删除异常:{}", e.getMessage());
			return R.fail(e.getMessage());
		}
	}

	@Operation(summary = "检测数据源配置是否正常")
	@Parameters({ @Parameter(name = "id", description = "数据源id", required = true) })
	@GetMapping("/check/{id}")
	public R<String> checkDbConfig(@PathVariable("id") String id) {
		try {
			DbConfig dbConfig = DbConfig.dao.findById(id);
			if (dbConfig != null && DbConfigTestUtil.isDataSourceHealthy(dbConfig)) {

				DataSourceValidator.ValidationResult result = DataSourceValidator.validateDataSource(dbConfig.getUrl(),
						dbConfig.getDriver(), dbConfig.getUsername(), dbConfig.getPassword(),
						dbConfig.getConnTimeout());

				if (result.isValid()) {
					return R.ok("数据源配置正确，连接正常.");
				} else {
					if (!result.isDriverValid()) {
						return R.fail("数据源配置错误:- 驱动类加载失败.");
					}
					if (!result.isConnectionValid()) {
						return R.fail("数据源配置错误:- 无法建立数据库连接.");
					}
					if (result.isConnectionValid() && !result.isConnectionAlive()) {
						return R.fail("数据源配置错误:- 连接建立但无法执行查询.");
					}
					return R.fail("错误详情: " + result.getErrorMessage());
				}

			} else {
				return R.fail("连接失败.");
			}
		} catch (Exception e) {
			log.error("连接异常:{}", e.getMessage());
			return R.fail(e.getMessage());
		}
	}
	
	@Operation(summary = "启动数据源")
	@Parameters({ @Parameter(name = "id", description = "数据源id", required = true) })
	@PostMapping("/start/{id}")
	public R<String> startDbConfig(@PathVariable("id") String id) {
		try {
			DbConfig dbConfig = DbConfig.dao.findById(id);
			if (dbConfig != null ) {
				DbConfigUtil.reload(id);
				return R.ok("执行成功,稍后刷新查看是否启动.");
			} else {
				return R.fail("启动失败,数据源不存在或数据源Id有误.");
			}
		} catch (Exception e) {
			log.error("启动异常:{}", e.getMessage());
			return R.fail(e.getMessage());
		}
	}
	
	@Operation(summary = "停止数据源")
	@Parameters({ @Parameter(name = "id", description = "数据源id", required = true) })
	@PostMapping("/stop/{id}")
	public R<String> stopDbConfig(@PathVariable("id") String id) {
		try {
			DbConfig dbConfig = DbConfig.dao.findById(id);
			if (dbConfig != null ) {
				DbConfigUtil.stopDatabase(id);
				return R.ok("执行成功,稍后刷新查看是否停止.");
			} else {
				return R.fail("停止数据源失败,数据源不存在或数据源Id有误.");
			}
		} catch (Exception e) {
			log.error("停止数据源异常:{}", e.getMessage());
			return R.fail(e.getMessage());
		}
	}

}
